package com.jinwei.qunguanjia.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jinwei.qunguanjia.system.dao.SysMenuDAO;
import com.jinwei.qunguanjia.system.dao.SysRoleMenuDAO;
import com.jinwei.qunguanjia.system.dto.SysMenuDTO;
import com.jinwei.qunguanjia.system.dto.SysRoleDTO;
import com.jinwei.qunguanjia.system.po.SysMenuPO;
import com.jinwei.qunguanjia.system.po.SysRoleMenuPO;
import com.jinwei.qunguanjia.system.utils.SecurityUtils;
import com.jinwei.qunguanjia.common.constant.UserConstants;
import com.jinwei.qunguanjia.common.core.domain.model.Condition;
import com.jinwei.qunguanjia.common.core.domain.model.Sort;
import com.jinwei.qunguanjia.common.enums.WrapperTypeEnum;
import com.jinwei.qunguanjia.common.utils.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 菜单配置 服务层实现类
 * @author yuanzs
 */
@Service("sysMenuService")
public class SysMenuServiceImpl implements SysMenuService {

    @Resource
    private SysMenuDAO sysMenuDAO;

    @Resource
    private SysRoleMenuDAO sysRoleMenuDAO;

    @Resource
    private SysRoleService sysRoleService;

    @Override
    public void save(SysMenuDTO sysMenuDTO) {
        SysMenuPO sysMenuPO = new SysMenuPO();
        BeanUtils.copyProperties(sysMenuDTO, sysMenuPO);
        sysMenuPO.setMenuId(IdUtils.getWorkerId());
        sysMenuDAO.insert(sysMenuPO);
    }

    @Override
    public void remove(String id) {
        sysMenuDAO.deleteById(id);
    }

    @Override
    public void update(SysMenuDTO sysMenuDTO) {
        SysMenuPO sysMenuPO = new SysMenuPO();
        BeanUtils.copyProperties(sysMenuDTO, sysMenuPO);
        sysMenuDAO.updateById(sysMenuPO);
    }

    @Override
    public SysMenuDTO get(String id) {
        SysMenuPO sysMenuPO = sysMenuDAO.selectById(id);
        SysMenuDTO sysMenuDTO = new SysMenuDTO();
        BeanUtils.copyProperties(sysMenuPO, sysMenuDTO);
        return sysMenuDTO;
    }

    @Override
    public SysMenuDTO get(SysMenuDTO sysMenuDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(sysMenuDTO);
        // 拼接查询条件
        QueryWrapper<SysMenuPO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        SysMenuPO sysUserPO = sysMenuDAO.selectOne(queryWrapper);
        if (null == sysUserPO){
            return null;
        }
        BeanUtils.copyProperties(sysUserPO, sysMenuDTO);
        return sysMenuDTO;


    }

    @Override
    public Long count(SysMenuDTO sysMenuDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(sysMenuDTO);
        // 拼接查询条件
        QueryWrapper<SysMenuPO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        return sysMenuDAO.selectCount(queryWrapper);
    }

    @Override
    public List<SysMenuDTO> list(SysMenuDTO sysMenuDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(sysMenuDTO);
        // 拼接查询条件
        QueryWrapper<SysMenuPO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        //拼接排序条件
        SearchUtils.parseOrderBySql(queryWrapper, sysMenuDTO.getSortList());
        return JsonUtils.copyList(sysMenuDAO.selectList(queryWrapper), SysMenuDTO.class);
    }

    @Override
    public Set<String> listMenuPermsByUserId(String userId) {
        List<String> perms = sysMenuDAO.listMenuPermsByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms) {
            if (StringUtils.isNotEmpty(perm)) {
                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
            }
        }
        return permsSet;
    }

    @Override
    public List<SysMenuDTO> listMenu(SysMenuDTO sysMenuDTO) throws IllegalAccessException {
        List<SysMenuDTO> menuList;
        // 管理员显示所有菜单信息
        if (SecurityUtils.isAdmin()) {
            menuList = list(sysMenuDTO);
        } else {
            sysMenuDTO.getParams().put("userId", SecurityUtils.getUserId());
            menuList = sysMenuDAO.listMenuByUserId(sysMenuDTO);
        }
        return menuList;
    }

    @Override
    public List<SysMenuDTO> listMenuTreeByUserId() throws IllegalAccessException {
        List<SysMenuDTO> menus;
        if (SecurityUtils.isAdmin()) {
            SysMenuDTO sysMenuDTO = new SysMenuDTO();
            sysMenuDTO.setMenuType(WrapperTypeEnum.IN.getType() + ":M,C");
            List<Sort> sortList = new ArrayList<>();
            sortList.add(new Sort("parent_id", Sort.ASC));
            sortList.add(new Sort("order_num", Sort.ASC));
            sysMenuDTO.setSortList(sortList);
            menus = list(sysMenuDTO);
        } else {
            menus = sysMenuDAO.listMenuTreeByUserId(SecurityUtils.getUserId());
        }
        return getChildPerms(menus);
    }

    @Override
    public List<String> listMenuByRoleId(String roleId) {
        SysRoleDTO sysRoleDTO = sysRoleService.get(roleId);
        return sysMenuDAO.listMenuByRoleId(roleId, sysRoleDTO.isMenuCheckStrictly());
    }

    @Override
    public String checkMenuNameUnique(SysMenuDTO sysMenuDTO) throws IllegalAccessException {
        String menuId = StringUtils.isNull(sysMenuDTO.getMenuId()) ? "-1" : sysMenuDTO.getMenuId();
        SysMenuDTO info = get(SysMenuDTO.builder().menuName(sysMenuDTO.getMenuName()).parentId(sysMenuDTO.getParentId()).build());
        if (StringUtils.isNotNull(info) && !info.getMenuId().equals(menuId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public boolean hasChildByMenuId(String menuId) throws IllegalAccessException {
        long result = count(SysMenuDTO.builder().menuId(menuId).build());
        return result > 0;
    }

    @Override
    public boolean checkMenuExistRole(String menuId) {
        LambdaQueryWrapper<SysRoleMenuPO> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.eq(SysRoleMenuPO::getMenuId, menuId);
        long result = sysRoleMenuDAO.selectCount(lambdaWrapper);
        return result > 0;
    }

    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list 分类表
     */
    private List<SysMenuDTO> getChildPerms(List<SysMenuDTO> list)
    {
        List<SysMenuDTO> returnList = new ArrayList<>();
        for (SysMenuDTO t : list) {
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId().equals("0")) {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     */
    private void recursionFn(List<SysMenuDTO> list, SysMenuDTO t)
    {
        // 得到子节点列表
        List<SysMenuDTO> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysMenuDTO tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysMenuDTO> getChildList(List<SysMenuDTO> list, SysMenuDTO t)
    {
        List<SysMenuDTO> listNew = new ArrayList<>();
        for (SysMenuDTO n : list) {
            if (n.getParentId().equals(t.getMenuId())) {
                listNew.add(n);
            }
        }
        return listNew;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysMenuDTO> list, SysMenuDTO t)
    {
        return getChildList(list, t).size() > 0;
    }
}
